package com.sojson.util.job;

import java.util.Date;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import com.sojson.config.task.TaskPoolConfig;
import com.sojson.enums.core.ESysJobStatus;
import com.sojson.project.monitor.job.entity.po.JobLog;
import com.sojson.project.monitor.job.service.ISysJobService;
import com.sojson.util.BeanUtil;
import com.sojson.util.SpringUtil;
import com.sojson.util.ThreadLocalUtil;
import com.sojson.util.ThreadUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * 抽象quartz调用
 *
 * @author lyh
 */
@Slf4j
public abstract class AbstractQuartzJob implements Job {

    private ISysJobService sysJobService = SpringUtil.getBeanByType(ISysJobService.class);

    /**
     * 线程本地变量
     */
    private static ThreadLocal<Date> threadLocal = new ThreadLocal<>();

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        ThreadUtil.setName(ThreadUtil.getName().replace("quartzScheduler_Worker-", TaskPoolConfig.KEY_TASK));
        int size = ThreadLocalUtil.HANDLERS.size();
        com.sojson.project.monitor.job.entity.po.Job job = null;

        try {
            for (int i = 0; i < size; i++) {
                ThreadLocalUtil.HANDLERS.get(i).runByTask();
            }
            job = new com.sojson.project.monitor.job.entity.po.Job();
            BeanUtil.copyBeanProp(job, context.getMergedJobDataMap().get(ScheduleConstant.TASK_PROPERTIES));

            before(context, job);
            if (job != null) {
                doExecute(context, job);
            }
            after(context, job, null);
        } catch (Exception e) {
            log.error("任务执行异常  - ：", e);
            after(context, job, e);
        } finally {
            try {
                threadLocal.remove();
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
            for (int i = size - 1; i > -1; i--) {
                try {
                    ThreadLocalUtil.HANDLERS.get(i).finallys();
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }

    /**
     * 执行前
     *
     * @param context 工作执行上下文对象
     * @param job  系统计划任务
     */
    protected void before(JobExecutionContext context, com.sojson.project.monitor.job.entity.po.Job job) {
        threadLocal.set(new Date());
    }

    /**
     * 执行后
     *
     * @param context 工作执行上下文对象
     * @param job  系统计划任务
     */
    protected void after(JobExecutionContext context, com.sojson.project.monitor.job.entity.po.Job job, Exception e) {
        Date startTime = threadLocal.get();

        final JobLog jobLog = new JobLog();
        jobLog.setName(job.getName());
        jobLog.setGroup(job.getGroup());
        jobLog.setInvokeTarget(job.getInvokeTarget());
        jobLog.setStartTime(startTime);
        jobLog.setStopTime(new Date());
        long runMs = jobLog.getStopTime().getTime() - jobLog.getStartTime().getTime();
        jobLog.setJobMessage(jobLog.getName() + " 总共耗时：" + runMs + "毫秒");
        if (e != null) {
            jobLog.setStatus(ESysJobStatus.FAIL.getCode());
            jobLog.setExceptionInfo(e.getMessage());
        } else {
            jobLog.setStatus(ESysJobStatus.SUCCESS.getCode());
        }

        // 写入数据库当中
        sysJobService.save(jobLog);
    }

    /**
     * 执行方法，由子类重载
     *
     * @param context 工作执行上下文对象
     * @param job  系统计划任务
     * @throws Exception 执行过程中的异常
     */
    protected abstract void doExecute(JobExecutionContext context, com.sojson.project.monitor.job.entity.po.Job job) throws Exception;

}